package org.budo.selenium.puppeteer;

import java.util.ArrayList;
import java.util.List;

import org.budo.selenium.AbstractBudoBrowserDriver;
import org.openqa.selenium.OutputType;

import com.ruiyun.jvppeteer.core.Puppeteer;
import com.ruiyun.jvppeteer.core.browser.Browser;
import com.ruiyun.jvppeteer.core.browser.BrowserFetcher;
import com.ruiyun.jvppeteer.core.page.Page;
import com.ruiyun.jvppeteer.options.LaunchOptions;
import com.ruiyun.jvppeteer.options.LaunchOptionsBuilder;
import com.ruiyun.jvppeteer.options.ScreenshotOptions;
import com.ruiyun.jvppeteer.options.Viewport;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * document.body.clientHeight
 * 
 * @author lmw
 */
@Getter
@Setter
@Slf4j
public class BudoPuppeteerBrowserDriver extends AbstractBudoBrowserDriver {
    private Integer width = 375; // iphone x

    private Integer height = 812 * 50; // iphone x // 高度无限

    private Integer deviceScaleFactor = 1;

    private Boolean isMobile = true;

    private Boolean hasTouch = true;

    private Boolean isLandscape = false;

    @Override
    public String pageSource(String url) {
        try {
            Browser browser = this.browser();

            Page page = browser.newPage();
            page.setUserAgent(this.getUserAgent());
            page.goTo(url);

            String content = page.content();

            // 用后关掉
            page.close();

            browser.close();
            browser.disconnect();

            return content;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <X> X screenshot(String url, OutputType<X> outputType) {
        try {
            log.info("#24 before screenshot, url=" + url + ", outputType=" + outputType);

            Browser browser = this.browser();

            Page page = browser.newPage();
            page.setUserAgent(this.getUserAgent());
            page.goTo(url);

            // Object clientHeight = page.evaluate("()=>{return document.body.clientHeight;}");
            // System.err.println("clientHeight=" + clientHeight);

            // Object offsetHeight = page.evaluate("()=>{return document.body.offsetHeight;}");
            // System.err.println("offsetHeight=" + offsetHeight);

            // Object scrollHeight = page.evaluate("()=>{return document.body.scrollHeight;}");
            // System.err.println("scrollHeight=" + scrollHeight);

            // Object availHeight = page.evaluate("()=>{return document.body.availHeight;}");
            // System.err.println("availHeight=" + availHeight);

            // Object documentElement = page.evaluate("()=>{return document.documentElement.clientHeight;}");
            // System.err.println("documentElement=" + documentElement);

            ScreenshotOptions screenshotOptions = new ScreenshotOptions();
            // screenshotOptions.setFullPage(true);

            // ElementHandle body = page.$("body"); // 只要 body 部分 控制图片高度
            String base64 = page.screenshot(screenshotOptions);
            log.info("#41 after screenshot, url=" + url + ", outputType=" + outputType);

            // 用后关掉
            page.close();

            browser.close();
            browser.disconnect();

            // 以指定格式 返回图片
            return outputType.convertFromBase64Png(base64);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    protected Viewport viewport() {
        return new Viewport(this.getWidth(), this.getHeight(), //
                this.getDeviceScaleFactor(), //
                this.getIsMobile(), this.getHasTouch(), this.getIsLandscape());
    }

    private Browser browser() throws Throwable {
        BrowserFetcher.downloadIfNotExist(null);

        List<String> args = new ArrayList<String>();
        args.add("--no-sandbox");

        Viewport viewport = this.viewport();

        LaunchOptions options = new LaunchOptionsBuilder() //
                .withArgs(args) //
                .withViewport(viewport) //
                .build();
        Browser browser = Puppeteer.launch(options);
        return browser;
    }
}